using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

using Data.GameData;
using Data.GameData.GameMap;

namespace Hexagonal
{
	public class GraphicsEngine
    {
        #region Attributes
        private Hexagonal.Board board;
		private int boardXOffset;
		private int boardYOffset;

        private string counterPath;
        #endregion

        #region Properties
        public int BoardXOffset
        {
            get
            {
                return boardXOffset;
            }
            set
            {
                throw new System.NotImplementedException();
            }
        }

        public int BoardYOffset
        {
            get
            {
                return boardYOffset;
            }
            set
            {
                throw new System.NotImplementedException();
            }
        }
        #endregion

        #region Constructors
        public GraphicsEngine(Hexagonal.Board board, string path)
            : this(board, 0, 0, path)
		{
		}

        public GraphicsEngine(Hexagonal.Board board, int xOffset, int yOffset, string path)
		{
			this.Initialize(board, xOffset, yOffset);
            counterPath = path + @"\Counters\";
        }

        private void Initialize(Hexagonal.Board board, int xOffset, int yOffset)
        {
            this.board = board;
            this.boardXOffset = xOffset;
            this.boardYOffset = yOffset;
        }
        #endregion

        #region DrawHexBoard
        bool boardChanged = true;
        Bitmap blankBoard = null;

        public void DrawHexBoard(Graphics graphics)
		{ 		
			int width =  Convert.ToInt32(System.Math.Ceiling(board.PixelWidth));
			int height = Convert.ToInt32(System.Math.Ceiling(board.PixelHeight));
			// seems to be needed to avoid bottom and right from being chopped off
			width += 1;
			height += 1;

            //
            // Create drawing objects
            //
            Bitmap bitmap = null;
            Graphics bitmapGraphics = null;
            Pen p = new Pen(Color.Black);
            SolidBrush sb = new SolidBrush(Color.Black);

            if (boardChanged)
            {
                bitmap = new Bitmap(width, height);
                bitmapGraphics = Graphics.FromImage(bitmap);

                //
                // Draw Board background
                //
                sb = new SolidBrush(board.BoardState.BackgroundColor);
                bitmapGraphics.FillRectangle(sb, 0, 0, width, height);

                //
                // Draw Hex Background 
                //
                for (int i = 0; i < board.Hexes.GetLength(0); i++)
                {
                    for (int j = 0; j < board.Hexes.GetLength(1); j++)
                    {
                        //bitmapGraphics.DrawPolygon(p, board.Hexes[i, j].Points);
                        bitmapGraphics.FillPolygon(new SolidBrush(board.Hexes[i, j].HexState.BackgroundColor), board.Hexes[i, j].Points);
                    }
                }

                //
                // Draw Hex Grid
                //
                p.Color = board.BoardState.GridColor;
                p.Width = board.BoardState.GridPenWidth;
                for (int i = 0; i < board.Hexes.GetLength(0); i++)
                {
                    for (int j = 0; j < board.Hexes.GetLength(1); j++)
                    {
                        bitmapGraphics.DrawPolygon(p, board.Hexes[i, j].Points);
                    }
                }

                boardChanged = false;
                blankBoard = bitmap.Clone() as Bitmap;
            }
            else
            {
                bitmap = blankBoard.Clone() as Bitmap;
                bitmapGraphics = Graphics.FromImage(bitmap);
            }

			//
			// Draw Active Hex, if present
			//
			if (board.BoardState.ActiveHex != null)
			{
				p.Color = board.BoardState.ActiveHexBorderColor;
				p.Width = board.BoardState.ActiveHexBorderWidth;
				bitmapGraphics.DrawPolygon(p, board.BoardState.ActiveHex.Points);
			}

			//
			// Draw internal bitmap to screen
			//
			graphics.DrawImage(bitmap, new Point(this.boardXOffset , this.boardYOffset));
			
			//
			// Release objects
			//
			bitmapGraphics.Dispose();
			bitmap.Dispose();
        }
        #endregion

        public void DrawHexMapContents(Graphics graphics, int mapId)
        {
            Bitmap curBitmap;
            int bitmapSize = 24;
            int bitmapHalfSize = (int)(bitmapSize / 2);

            int width = Convert.ToInt32(System.Math.Ceiling(board.PixelWidth));
            int height = Convert.ToInt32(System.Math.Ceiling(board.PixelHeight));
            // seems to be needed to avoid bottom and right from being chopped off
            width += 1;
            height += 1;
            
            // Create drawing objects
            Bitmap bitmap = new Bitmap(width, height);
            Graphics bitmapGraphics = Graphics.FromImage(bitmap);

            foreach (MapObject obj in Map.GetMapContents(mapId))
            {
                curBitmap = new Bitmap(counterPath + obj.ImageName);
                Point centre = board.Hexes[obj.MapPosition.Row, obj.MapPosition.Column].Centre;

                // Transform the bitmap to the correct possition
                Matrix X = new Matrix();
                X.Translate(centre.X - bitmapHalfSize, centre.Y - bitmapHalfSize);
                X.RotateAt(60 * obj.Heading, new PointF(bitmapHalfSize, bitmapHalfSize));
                bitmapGraphics.Transform = X;

                bitmapGraphics.DrawImage(curBitmap, 0, 0, bitmapSize, bitmapSize);
            }

            // Draw internal bitmap to screen
            graphics.DrawImage(bitmap, new Point(this.boardXOffset, this.boardYOffset));

            // Release objects
            bitmapGraphics.Dispose();
            bitmap.Dispose();
        }
	}
}
